# coding:utf-8
'''
编写人：zhaogq
时间：2024-10-15
该模块需要安装
pip install reportlab       # 输出PDF
pip install qrcode[pil]     # 二维码
pip install barcode         # 条码
'''

from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A5
from reportlab.lib.units import inch
from reportlab.platypus import Image as ImageDraw 
from PIL import Image
import qrcode
import base64
import os
from base import getHosp
 
# 生成二维码函数
def generateQrcode(data):
    qr=qrcode.QRCode(
        version=1,
        error_correction=qrcode.constants.ERROR_CORRECT_L,
        box_size=2,
        border=1,
    )
    qr.add_data(data)
    qr.make(fit=True)
    img=qr.make_image(fill='black', back_color='white')
    return img    
 
def drawText(c, pagesize, x, y, type, str, fontName, fontSize):
    c.setFont(fontName, fontSize)
    if type=='center':
        c.drawCentredString(x,y,str)
    elif type=='right':
        c.drawRightString(x,y,str)
    else:
        c.drawString(x,y,str)
    return 
 
def initPresOut(pdf_filename):
    # 加载中文字体
    pdfmetrics.registerFont(TTFont('SimFang', 'simfang.ttf'))
    pdfmetrics.registerFont(TTFont('SimHei', 'simhei.ttf'))
    pdfmetrics.registerFont(TTFont('XingKa', 'STXINGKA.ttf'))
    # 新建一个PDF文档
    c=canvas.Canvas(pdf_filename, pagesize=A5)
    return c
    
def title(c, title, pres_id):
    width, height=A5
    # 打印标题
    drawText(c,A5,width/2,560,'center',title,'SimFang',16)
    drawText(c,A5,width/2,540,'center','普通处方笺（外配）','SimFang',16)
    drawText(c,A5,360,560,'left','普通','SimFang',16)
    drawText(c,A5,360,540,'left','处方','SimFang',16)
    # 绘制矩形
    x1,y1=350,580
    x2, y2=400,530
    c.setLineWidth(1.5)
    c.rect(x1,y1,x2 - x1,y2-y1,fill=0)
    c.setLineWidth(1)
    # 二维码
    img=generateQrcode(pres_id)
    img.save('qrcode.jpg')
    img1=ImageDraw('qrcode.jpg')
    img1.drawOn(c, 20,530)
    
   
def getPres():
    ret={
        'pres_id': '900040000024',
        'patient_id': 1078,
        'patient_name': '张玉香',
        'patient_sex': '女',
        'patient_age': 59,
        'patient_id_card': '370829196109055628',
        'patient_addr': '开元乐都养老院',
        'patient_contact_tel': '',
        'sect_id': 2,
        'sect_name': '内科',
        'doct_id': 4,
        'doctor_name': '傅伟浩',
        'amount': 8.7,
        'diag_id': 85117,
        'pres_date': '2025-01-04 07:40:48',
        'icds': [
            'A04.01.09',
            'A01.01.02.02',
            'A08.02.01.04'
        ],
        'icdnames': '惊悸病,冒暑病,蝼蛄疖病',
        'list': [
            {
                'pres_id': '900040000024',
                'seq': 1,
                'name': '乙 西地碘含片',
                'medi_mark_id': 685,
                'spec': '1.5mg*24s//北京华素',
                'quantity': 1,
                'resale_price': 6.8,
                'amount': 6.8,
                'zxts': 1,
                'medi_doage': '1',
                'medi_pass': 5,
                'medi_pass_name': '口服',
                'unit_id': 4,
                'unit_name': '盒',
                'medi_unit_id': 1,
                'medi_unit_name': '片',
                'use_type_id': 1,
                'use_type_name': '一天一次'
            },
            {
                'pres_id': '900040000024',
                'seq': 2,
                'name': '丙 碘酊',
                'medi_mark_id': 768,
                'spec': '20ml//广东恒健',
                'quantity': 1,
                'resale_price': 1.9,
                'amount': 1.9,
                'zxts': 1,
                'medi_doage': '1',
                'medi_pass': 7,
                'medi_pass_name': '外用',
                'unit_id': 4,
                'unit_name': '盒',
                'medi_unit_id': 13,
                'medi_unit_name': 'ml',
                'use_type_id': 1,
                'use_type_name': '一天一次'
            }
        ]
    }
    ret={
        "pres_id": "900040000024",
        "patient_id": 1078,
        "patient_name": "张玉香",
        "patient_sex": "女",
        "patient_age": 59,
        "patient_id_card": "370829196109055628",
        "patient_addr": "开元乐都养老院",
        "patient_contact_tel": "None",
        "sect_id": 2,
        "sect_name": "内科",
        "doct_id": 4,
        "doctor_name": "傅伟浩",
        "amount": 8.7,
        "diag_id": 85117,
        "pres_date": "2025-01-04 07:40:48",
        "icds": [
            "A04.01.09",
            "A01.01.02.02",
            "A08.02.01.04"
        ],
        "icdnames": "惊悸病,冒暑病,蝼蛄疖病",
        "valid_days": 7,
        "list": [
            {
                "pres_id": "900040000024",
                "seq": 1,
                "name": "乙 西地碘含片",
                "medi_mark_id": 685,
                "spec": "1.5mg*24s//北京华素",
                "quantity": 1,
                "resale_price": 6.8,
                "amount": 6.8,
                "zxts": 1,
                "medi_doage": "1",
                "medi_pass": 5,
                "medi_pass_name": "口服",
                "unit_id": 4,
                "unit_name": "盒      ",
                "medi_unit_id": 1,
                "medi_unit_name": "片      ",
                "use_type_id": 1,
                "use_type_name": "一天一次"
            },
            {
                "pres_id": "900040000024",
                "seq": 2,
                "name": "丙 碘酊",
                "medi_mark_id": 768,
                "spec": "20ml//广东恒健",
                "quantity": 1,
                "resale_price": 1.9,
                "amount": 1.9,
                "zxts": 1,
                "medi_doage": "1",
                "medi_pass": 7,
                "medi_pass_name": "外用",
                "unit_id": 4,
                "unit_name": "盒      ",
                "medi_unit_id": 13,
                "medi_unit_name": "ml      ",
                "use_type_id": 1,
                "use_type_name": "一天一次"
            }
        ]
    }
    return ret

def presOut(presData, c):
    # 宽度，高度
    w,h=A5
    # 获取处方数据
    presData=presData
    # 输出标题
    hosp=getHosp()['data']['name']
    title(c,hosp,presData['pres_id'])
    # 输出参数定义
    fontSize=9
    lineHeight=15
    # 编号
    drawText(c,A5,20,510-(lineHeight*0),'left','No:'+presData['pres_id'],'SimFang',fontSize)
    # 姓名，性别，年龄
    drawText(c,A5,20,510-(lineHeight*1),'left','姓名:'+presData['patient_name'],'SimFang',fontSize)
    drawText(c,A5,150,510-(lineHeight*1),'left','性别:'+presData['patient_sex'],'SimFang',fontSize)
    drawText(c,A5,260,510-(lineHeight*1),'left','年龄:'+str(presData['patient_age']),'SimFang',fontSize)
    # 门诊病历号，科别
    drawText(c,A5,20,510-(lineHeight*2),'left','门诊病历号:'+str(presData['patient_id']),'SimFang',fontSize)
    drawText(c,A5,260,510-(lineHeight*2),'left','科别:'+presData['sect_name'],'SimFang',fontSize)
    # 地址，电话
    drawText(c,A5,20,510-(lineHeight*3),'left','地址:'+presData['patient_addr'],'SimFang',fontSize)
    drawText(c,A5,260,510-(lineHeight*3),'left','电话:'+presData['patient_contact_tel'],'SimFang',fontSize)
    # 临床（初步）诊断及证型
    drawText(c,A5,20,510-(lineHeight*4),'left','临床（初步）诊断及证型:'+presData['icdnames'],'SimFang',fontSize)
    # 开方日期
    drawText(c,A5,20,510-(lineHeight*5),'left','开方日期:'+presData['pres_date'][0:10],'SimFang',fontSize)
    # 开方日期
    drawText(c,A5,20,510-(lineHeight*6),'left','Rp:','SimFang',14)
    # 处方明细
    startPos=400
    idx=0
    lineHeight=30
    for item in presData['list']:
        # 第一行，序号、名称、规格
        drawText(c,A5,20,startPos-(lineHeight*idx)-2,'left',str(idx+1),'SimFang',12)
        drawText(c,A5,40,startPos-(lineHeight*idx),'left',item['name'],'SimFang',fontSize)
        drawText(c,A5,200,startPos-(lineHeight*idx),'left',item['spec'],'SimFang',fontSize)
        drawText(c,A5,400,startPos-(lineHeight*idx),'right',str(item['quantity'])+item['unit_name'],'SimFang',fontSize)
        # 第二行，用法，途径，频次，天数
        drawText(c,A5,40,startPos-(lineHeight*idx)-lineHeight/2+5,'left','用法：'+item['medi_doage']+item['medi_unit_name']+'/次','SimFang',fontSize)
        drawText(c,A5,140,startPos-(lineHeight*idx)-lineHeight/2+5,'left',item['medi_pass_name'],'SimFang',fontSize)
        drawText(c,A5,220,startPos-(lineHeight*idx)-lineHeight/2+5,'left',item['use_type_name'],'SimFang',fontSize)
        drawText(c,A5,400,startPos-(lineHeight*idx)-lineHeight/2+5,'right','执行天数：'+str(item['zxts'])+'天','SimFang',fontSize)
        idx=idx+1
    # 画斜线
    x1,y1,x2,y2=20,140,400,startPos-lineHeight*idx
    c.line(x1,y1,x2,y2)
    # 输出结束部分（药费）
    c.setLineWidth(1.5)
    x1,y1,x2,y2=20,120,150,80
    c.rect(x1,y1,x2-x1,y2-y1,fill=0)
    drawText(c,A5,(x1+x2)/2,95,'center','药费￥'+str(presData['amount']),'SimFang',14)
    c.setLineWidth(1)
    # 收费盖章
    drawText(c,A5,w/2,105,'center','收费','SimFang',14)
    drawText(c,A5,w/2,90,'center','盖章','SimFang',14)
    # 医师（签名），配药药师、复核药师
    x=250
    t='医师（签名）：'
    drawText(c,A5,x,115,'left',t,'SimFang',9)
    x1,y1,x2,y2=x+c.stringWidth(t),112,400,112
    c.line(x1,y1,x2,y2)
    drawText(c,A5,(x1+x2)/2,y1+5,'center',presData['doctor_name'],'XingKa',14)
    t='审核药师（签名）：'
    drawText(c,A5,x,100,'left',t,'SimFang',9)
    x1,y1,x2,y2=x+c.stringWidth(t),97,400,97
    c.line(x1,y1,x2,y2)
    t='配药药师（签名）：'
    drawText(c,A5,x,85,'left',t,'SimFang',9)
    x1,y1,x2,y2=x+c.stringWidth(t),82,400,82
    c.line(x1,y1,x2,y2)
    t='复核药师（签名）：'
    drawText(c,A5,x,70,'left',t,'SimFang',9)
    x1,y1,x2,y2=x+c.stringWidth(t),67,400,82
    c.line(x1,y1,x2,y2)    # 备注说明
    t='注意：请勿遗失，处方当日有效。因特殊情况，该处方有效期为'+ str(presData['valid_days'])+'天（签名：'
    drawText(c,A5,20,50,'left',t,'SimFang',9)
    drawText(c,A5,80+c.stringWidth(t),50,'left','）','SimFang',9)
    x1,y1,x2,y2=20+c.stringWidth(t),50,80+c.stringWidth(t),50
    c.line(x1,y1,x2,y2)
    drawText(c,A5,(x1+x2)/2,y1+5,'center',presData['doctor_name'],'XingKa',14)

def presToPdfBase64(presData):
    # 指定PDF文件名
    pdfFilename="{}.pdf".format(presData['pres_id'])
    c=initPresOut(pdfFilename)
    presOut(presData,c)
    c.save()
    with open(pdfFilename, 'rb') as file:
        pdf_data = file.read()
        base64_pdf = base64.b64encode(pdf_data).decode('utf-8')
    # 删除pdf临时文件
    os.remove(pdfFilename)
    # 返回数据
    return base64_pdf
    
def main():
    # 获取测试数据
    presData=getPres()
    ret=presToPdfBase64(presData)
    pdf_data = base64.b64decode(ret)
    with open('base64ToPdf.pdf', 'wb') as file:
        file.write(pdf_data)
if __name__ == '__main__':
    main()